package com.skycan.plc.adapter.service;

import com.skycan.plc.adapter.model.DeviceInfo;
import com.skycan.plc.adapter.model.DeviceInfo.DeviceType;
import com.skycan.plc.adapter.protocol.ProtocolAdapter;
import com.skycan.plc.adapter.protocol.modbus.ModbusRtuAdapter;
import com.skycan.plc.adapter.protocol.s7.S7_1200Adapter;
import com.skycan.plc.adapter.protocol.s7.S7_200Adapter;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 设备管理服务
 */
public class DeviceService {
    private static final Logger logger = LoggerFactory.getLogger(DeviceService.class);

    // 设备信息映射表
    private final Map<String, DeviceInfo> deviceInfoMap = new ConcurrentHashMap<>();

    // 设备通道映射表
    private final Map<String, Channel> deviceChannelMap = new ConcurrentHashMap<>();

    // 协议适配器映射表
    private final Map<DeviceType, ProtocolAdapter> adapterMap = new ConcurrentHashMap<>();

    public DeviceService() {
        // 初始化协议适配器
        initProtocolAdapters();
    }

    /**
     * 初始化协议适配器
     */
    private void initProtocolAdapters() {
        adapterMap.put(DeviceType.S7_200, new S7_200Adapter());
        adapterMap.put(DeviceType.S7_1200, new S7_1200Adapter());
        adapterMap.put(DeviceType.MODBUS_RTU, new ModbusRtuAdapter());

        logger.info("协议适配器初始化完成");
    }

    /**
     * 注册设备
     *
     * @param deviceInfo 设备信息
     * @param channel    设备通道
     */
    public void registerDevice(DeviceInfo deviceInfo, Channel channel) {
        String deviceId = deviceInfo.getDeviceId();

        // 存储设备信息
        deviceInfoMap.put(deviceId, deviceInfo);

        // 存储设备通道
        deviceChannelMap.put(deviceId, channel);

        logger.info("设备注册成功: {}, 类型: {}", deviceId, deviceInfo.getDeviceType());
    }

    /**
     * 移除设备通道
     *
     * @param deviceId 设备ID
     */
    public void removeDeviceChannel(String deviceId) {
        deviceChannelMap.remove(deviceId);
        logger.info("设备通道移除: {}", deviceId);
    }

    /**
     * 更新设备状态
     *
     * @param deviceId 设备ID
     * @param status   设备状态
     */
    public void updateDeviceStatus(String deviceId, DeviceInfo.DeviceStatus status) {
        DeviceInfo deviceInfo = deviceInfoMap.get(deviceId);
        if (deviceInfo != null) {
            deviceInfo.setStatus(status);
            deviceInfoMap.put(deviceId, deviceInfo);
            logger.info("设备状态更新: {}, 状态: {}", deviceId, status);
        }
    }

    /**
     * 更新设备最后通信时间
     *
     * @param deviceId 设备ID
     * @param time     通信时间
     */
    public void updateLastCommunicationTime(String deviceId, long time) {
        DeviceInfo deviceInfo = deviceInfoMap.get(deviceId);
        if (deviceInfo != null) {
            deviceInfo.setLastCommunicationTime(time);
            deviceInfoMap.put(deviceId, deviceInfo);
        }
    }

    /**
     * 设置设备类型
     *
     * @param deviceId   设备ID
     * @param deviceType 设备类型
     */
    public void setDeviceType(String deviceId, DeviceType deviceType) {
        DeviceInfo deviceInfo = deviceInfoMap.get(deviceId);
        if (deviceInfo != null) {
            deviceInfo.setDeviceType(deviceType);
            deviceInfoMap.put(deviceId, deviceInfo);
            logger.info("设备类型设置: {}, 类型: {}", deviceId, deviceType);

            // 连接设备
            connectDevice(deviceId);
        }
    }

    /**
     * 获取设备信息
     *
     * @param deviceId 设备ID
     * @return 设备信息
     */
    public DeviceInfo getDeviceInfo(String deviceId) {
        return deviceInfoMap.get(deviceId);
    }

    /**
     * 获取设备通道
     *
     * @param deviceId 设备ID
     * @return 设备通道
     */
    public Channel getDeviceChannel(String deviceId) {
        return deviceChannelMap.get(deviceId);
    }

    /**
     * 获取设备适配器
     *
     * @param deviceType 设备类型
     * @return 协议适配器
     */
    public ProtocolAdapter getProtocolAdapter(DeviceType deviceType) {
        return adapterMap.get(deviceType);
    }

    /**
     * 连接设备
     *
     * @param deviceId 设备ID
     * @return 是否连接成功
     */
    public boolean connectDevice(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoMap.get(deviceId);
        if (deviceInfo == null || deviceInfo.getDeviceType() == null) {
            logger.error("设备类型未设置: {}", deviceId);
            return false;
        }

        ProtocolAdapter adapter = adapterMap.get(deviceInfo.getDeviceType());
        if (adapter == null) {
            logger.error("找不到适配器: {}, 类型: {}", deviceId, deviceInfo.getDeviceType());
            return false;
        }

        return adapter.connect(deviceInfo);
    }

    /**
     * 断开设备连接
     *
     * @param deviceId 设备ID
     */
    public void disconnectDevice(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoMap.get(deviceId);
        if (deviceInfo != null && deviceInfo.getDeviceType() != null) {
            ProtocolAdapter adapter = adapterMap.get(deviceInfo.getDeviceType());
            if (adapter != null) {
                adapter.disconnect(deviceInfo);
            }
        }

        // 移除设备信息
        deviceInfoMap.remove(deviceId);

        logger.info("设备连接断开: {}", deviceId);
    }

    /**
     * 获取所有设备信息
     *
     * @return 设备信息映射表
     */
    public Map<String, DeviceInfo> getAllDeviceInfo() {
        return deviceInfoMap;
    }
}